package com.shanpin.shebao.utility;

import java.awt.image.BufferedImage;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import javax.imageio.ImageIO;
import javax.imageio.stream.ImageOutputStream;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.shanpin.core.utils.StringUtil;
import com.shanpin.shebao.admin.module.material.model.MaterialDownload;
  
public class Downloader {
	
	private static Logger logger = LoggerFactory.getLogger(Downloader.class);

	/**
	 * 批量下载材料
	 */
	public static void batchDownloadMaterial(List<MaterialDownload> materialList, 
			OutputStream outputStream) throws Exception {
		if(materialList == null || materialList.size()<1) {
			return;
		}
		ZipOutputStream out = new ZipOutputStream(outputStream);  
		BufferedOutputStream bo = new BufferedOutputStream(out); 
		try{
			//批量下载的材料，尝试合并记录生成一份excel下载
			Map<String, Workbook> mergeMap = new HashMap<>(8);
			List<MaterialDownload> restMaterialList = new ArrayList<>(materialList.size());
			for(MaterialDownload material : materialList) {
				boolean merged = false;
				String url = StringUtil.getNotNullStr(material.getUrl());
				String city = StringUtil.getNotNullStr(material.getCity());
				int city_code = material.getCity_code()==null?0:material.getCity_code();
				if(url.endsWith("_999.xls")) {
					try{
						String[] titles = null;
						if(city_code == 2705) { //保定
							titles = "身份证号#银行卡号#开户银行#开户支行".split("#");
						} else if(city_code == 1101) { //北京
							titles = "身份证号#银行卡号#开户银行#开户支行".split("#");
						} else if(city_code == 1201) { //上海
							titles = "身份证号#政治面貌#学历#婚姻状况#户籍地址#现居住地址".split("#");
						} else { //其它
							titles = "身份证号#政治面貌#学历#婚姻状况".split("#");
						}
						Workbook workbook = WorkbookFactory.create(new ByteArrayInputStream(getFileByUrl(url)));
						Sheet sheet = workbook.getSheetAt(0);
						Row titleRow = sheet.getRow(0);
						boolean canMerge = true;
						for(int i=0, len=titles.length; i<len; i++) {
							if(!titles[i].equals(titleRow.getCell(i).getStringCellValue())) {
								canMerge = false;
							}
						}
						if(canMerge) {
							Row dataRow = sheet.getRow(1);
							Workbook mergeWorkbook = mergeMap.get(city);
							if(mergeWorkbook == null) {
								mergeWorkbook = new HSSFWorkbook();
								Sheet s = mergeWorkbook.createSheet(material.getCity());
								Row r = s.createRow(0);
								for(int i=0, len=titles.length; i<len; i++) {
									r.createCell(i).setCellValue(titles[i]);
								}
							}
							Sheet mergeSheet = mergeWorkbook.getSheetAt(0);
							Row mergeDataRow = mergeSheet.createRow(mergeSheet.getLastRowNum()+1);
							for(int i=0, len=titles.length; i<len; i++) {
								mergeDataRow.createCell(i).setCellValue(dataRow.getCell(i).getStringCellValue());
								mergeSheet.autoSizeColumn(i);
							}
							merged=true;
							mergeMap.put(city, mergeWorkbook);
						}
					} catch (Exception e) {
						logger.error("excel下载合并出错", e);
					}
				}
				if(!merged) {
					restMaterialList.add(material);
				}
			}
			
			for(Map.Entry<String, Workbook> entry : mergeMap.entrySet()) {
				String city = entry.getKey();
				Workbook workbook = entry.getValue();
				ByteArrayOutputStream bos = new ByteArrayOutputStream();
				workbook.write(bos);
				String fileName = city+"_参保数据.xls";
				addZip(out, new ByteArrayInputStream(bos.toByteArray()), fileName);
				bos.close();
				workbook.close();
			}
			
			Set<String> urlSet = new HashSet<>();
			for(MaterialDownload material : restMaterialList) {
				String city = StringUtil.getNotNullStr(material.getCity());
				String sourceName = StringUtil.getNotNullStr(material.getSource_name());
				String userName = StringUtil.getNotNullStr(material.getUser_name());
				String idCard = StringUtil.getNotNullStr(material.getId_card());
				String url = StringUtil.getNotNullStr(material.getUrl());
				if(urlSet.add(url)) {
					String fileName = city + "_" + sourceName +  "_" + userName + "_" + idCard + "_" + url.substring(url.lastIndexOf("/") + 1, url.length());
					byte[] b = getFileByUrl(url);
					if(b != null && b.length > 0) {
						addZip(out, new ByteArrayInputStream(b), fileName);
					}
				}
			}
		} finally {
			if(bo != null) {
				bo.close();
			}
			if(out != null) {
				out.close();
			}
		}
	}
	
	/**
	 * 批量下载身份证
	 * 只下载合并后的图片
	 */
	public static void batchDownloadIdCard(List<IdCardModel> idCardModelList, 
			OutputStream outputStream) throws Exception {
		if(idCardModelList == null) {
			return;
		}
		ZipOutputStream out = new ZipOutputStream(outputStream);  
		BufferedOutputStream bo = new BufferedOutputStream(out); 
		try{
			for(IdCardModel idCardModel : idCardModelList) {
				String userName = idCardModel.getUser_name();
				String idCard = idCardModel.getId_card();
				String url0 = idCardModel.getUrl0();	//正面身份证
				String url1 = idCardModel.getUrl1();	//反面身份证
				
				InputStream  inputStream0 = null; //处理正面身份证
				byte[] b0 = getFileByUrl(url0);
				if(b0 != null && b0.length > 0) {
					inputStream0 = new ByteArrayInputStream(b0); 
				}
				
				InputStream  inputStream1 = null; //处理反面身份证
				byte[] b1 = getFileByUrl(url1);
				if(b1 != null && b1.length > 0) {
					inputStream1 = new ByteArrayInputStream(b1); 
				}
				
				//合并图片
				if(inputStream0 != null && inputStream1 != null) {
					try{
						InputStream inputStreamMerge = mergeIdCard(inputStream0, inputStream1);
						if(inputStreamMerge != null) {
				        	String fileName = userName + "_" + idCard+".jpg";
				        	addZip(out, inputStreamMerge, fileName);
				        }
					} catch (Exception e) {
					} finally {
						if(inputStream0 != null) {
							inputStream0.close();
						}
						if(inputStream1 != null) {
							inputStream1.close();
						}
					}
				}
			}
		} finally {
			if(bo != null) {
				bo.close();
			}
			if(out != null) {
				out.close();
			}
		}
	}
	
	/**
	 * 身份证下载
	 * 原图与合并后的图片都下载
	 */
	public static void downloadIdCard(IdCardModel idCardModel,
			OutputStream outputStream) throws Exception {
		if(idCardModel == null) {
			return;
		}
		String userName = idCardModel.getUser_name();
		String idCard = idCardModel.getId_card();
		List<String> urlList = new ArrayList<String>();
		if(idCardModel.getUrl0() != null) {
			urlList.add(idCardModel.getUrl0());
		}
		if(idCardModel.getUrl1() != null) {
			urlList.add(idCardModel.getUrl1());
		}
		String[] urls = new String[urlList.size()];
		urlList.toArray(urls);
		
		if(urls.length < 2) {
			zipFromUrls(urls, outputStream);
			return;
		}
		
		ZipOutputStream out = new ZipOutputStream(outputStream);  
		BufferedOutputStream bo = new BufferedOutputStream(out); 
		
		InputStream  inputStream0 = null; //处理正面身份证
		InputStream  inputStream1 = null; //处理反面身份证
		try{
			String url0 = urls[0];	//正面身份证
			String url1 = urls[1];	//反面身份证
			
			String fileName0 = userName + "_" + idCard + "_" + url0.substring(url0.lastIndexOf("/") + 1, url0.length());
			byte[] b0 = getFileByUrl(url0);
			if(b0 != null && b0.length > 0) {
				inputStream0 = new ByteArrayInputStream(b0); 
			}
			
			String fileName1 = userName + "_" + idCard + "_" + url1.substring(url1.lastIndexOf("/") + 1, url1.length());
			byte[] b1 = getFileByUrl(url1);
			if(b1 != null && b1.length > 0) {
				inputStream1 = new ByteArrayInputStream(b1); 
			}
			
			//合并图片
			if(inputStream0 != null && inputStream1 != null) {
				InputStream is0 = new ByteArrayInputStream(b0);
				InputStream is1 = new ByteArrayInputStream(b1);
				try{
					InputStream inputStreamMerge = mergeIdCard(is0, is1);
			        if(inputStreamMerge != null) {
			        	String fileName = userName + "_" + idCard+".jpg";
			        	addZip(out, inputStreamMerge, fileName);
			        }
				} catch (Exception e) {
				} finally {
					if(is0 != null) {
						is0.close();
					}
					if(is1 != null) {
						is1.close();
					}
				}
			}
			//身份证正面
			if(inputStream0 != null) {
				addZip(out, inputStream0, fileName0);
			}
			//身份证反面
			if(inputStream1 != null) {
				addZip(out, inputStream1, fileName1);
			}
		} finally {
			if(inputStream0 != null) {
				inputStream0.close();
			}
			if(inputStream1 != null) {
				inputStream1.close();
			}
			if(bo != null) {
				bo.close();
			}
			if(out != null) {
				out.close();
			}
		}
	}

	/**
	 * 生成一个合并的图片
	 */
	private static InputStream mergeIdCard(InputStream is0, InputStream is1) {
		try {
			BufferedImage idCardImg0 = ImageIO.read(is0);
			int[] idCardImgArr0 = new int[idCardImg0.getWidth() * idCardImg0.getHeight()];
			idCardImgArr0 = idCardImg0.getRGB(0, 0, idCardImg0.getWidth(), idCardImg0.getHeight(), idCardImgArr0, 0, idCardImg0.getWidth());
			
			BufferedImage idCardImg1 = ImageIO.read(is1);
			int[] idCardImgArr1 = new int[idCardImg1.getWidth() * idCardImg1.getHeight()];
			idCardImgArr1 = idCardImg1.getRGB(0, 0, idCardImg1.getWidth(), idCardImg1.getHeight(), idCardImgArr1, 0, idCardImg1.getWidth());
			
			int width = Math.max(idCardImg0.getWidth(), idCardImg1.getWidth());
			int height = idCardImg0.getHeight() + idCardImg1.getHeight();
			
			BufferedImage idCardImgMerge = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
			idCardImgMerge.setRGB(0, 0, idCardImg0.getWidth(), idCardImg0.getHeight(), 
					idCardImgArr0, 0, idCardImg0.getWidth());
			idCardImgMerge.setRGB(0, idCardImg0.getHeight(), idCardImg1.getWidth(), idCardImg1.getHeight(), 
					idCardImgArr1, 0, idCardImg1.getWidth());
	        
	        ByteArrayOutputStream baos = new ByteArrayOutputStream();
	        ImageOutputStream ios = ImageIO.createImageOutputStream(baos);
	        ImageIO.write(idCardImgMerge, "jpg", ios);
	        
	        InputStream inputStreamMerge = new ByteArrayInputStream(baos.toByteArray());
	        return inputStreamMerge;
		} catch (Exception e) {
		}
		return null;
	}
	
	
	/**
	 * 下载指定url文件内容到压缩包里面
	 * @param urls
	 * @param outputStream
	 * @throws Exception
	 */
	public static void zipFromUrls(String[] urls, OutputStream outputStream) throws Exception {
		ZipOutputStream out = new ZipOutputStream(outputStream);  
		BufferedOutputStream bo = new BufferedOutputStream(out); 
		
		writeToZip(out, urls);
		
		bo.close();  
		out.close(); // 输出流关闭  
	}

	private static void writeToZip(ZipOutputStream out, String[] urls) throws Exception {
		for(String url: urls) {
			InputStream  inputStream = null;
			
			String fileName = url.substring(url.lastIndexOf("/")+1, url.length());
			
			byte[] b = null;
			b = getFileByUrl(url);
			
			if(b != null && b.length > 0) {
				 inputStream = new ByteArrayInputStream(b); 
				
			}
			
			if(inputStream != null) {
				addZip(out, inputStream, fileName);
			}
		      
		}
	}  
    
	private static  byte[] getFileByUrl(String strUrl){
		int connectTimeout = 3000;
		int readTimeout = 3000;
    	HttpURLConnection conn = null;
    	InputStream inStream = null;
        try {  
        	if(strUrl != null && !"".equals(strUrl)){
        		URL url = new URL(strUrl);  
        		conn = (HttpURLConnection)url.openConnection();  
        		conn.setRequestMethod("GET");  
        		conn.setConnectTimeout(connectTimeout == 0 ? 5 * 1000 : connectTimeout);  
        		conn.setReadTimeout(readTimeout == 0 ? 30 * 1000 : readTimeout);
        		conn.setDoInput(true);
        		inStream = conn.getInputStream();
        		byte[] btFile = readInputStream(inStream);
        		return btFile;
        	}
        } catch (Exception e) {  
            e.printStackTrace();  
        } finally {
        	if(inStream != null) {
        		try {
					inStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
        	}
        	if(conn != null) {
        		conn.disconnect();
        	}
        		
        }  
        return null;  
    }  
	
    private static  byte[] readInputStream(InputStream inStream) throws Exception{  
        ByteArrayOutputStream outStream = new ByteArrayOutputStream();  
        byte[] buffer = new byte[1024];  
        int len = 0;  
        while( (len=inStream.read(buffer)) != -1 ){  
            outStream.write(buffer, 0, len);  
        }  
        inStream.close();  
        return outStream.toByteArray();  
    }
  
    private static  void addZip(ZipOutputStream out, InputStream in, String base) throws Exception { // 方法重载  
    	
    	out.putNextEntry(new ZipEntry(base)); // 创建zip压缩进入点base 
    	
        BufferedInputStream bi = new BufferedInputStream(in);  
        int b;  
        while ((b = bi.read()) != -1) {  
        	out.write(b); // 将字节流写入当前zip目录  
        }  
        bi.close();  
        in.close(); // 输入流关闭  
    }  
}  
